package cn.tedu.charging.order.config;



import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;


@Slf4j
@Configuration
public class RabbitMQConfig {

    //给rabbitmq配置
    public RabbitMQConfig(RabbitTemplate rabbitTemplate) {
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnsCallback((returnedMessage)->{
            log.debug("returnedMessage= {}",returnedMessage);
        });
        rabbitTemplate.setConfirmCallback((data,ack,cause)->{
            log.debug("data= {},ack= {},cause= {}",data,ack,cause);
            if (ack) {
                log.debug("Message confirmed: {}", ack);
            } else {
                log.warn("Message failed: {}", cause);
            }
        });
    }


    public static final String EXCHANGE_NAME = "charging_order_exchange";

    public static final String QUEUE_NAME = "charging_order_queue";

    public static final String ROUTING_KEY = "charging_order_routing_key";

    private static final String DEAD_LETTER_EXCHANGE_NAME = "dead_letter_charging_order_exchange";

    public static final String DEAD_LETTER_QUEUE_NAME = "dead_letter_charging_order_queue";

    private static final String DEAD_LETTER_ROUTING_KEY = "dead_letter_charging_order_routing_key";

    //DeadLetter 死信队列  正常计时队列设置超时后  超时会被移入死信队列
    /**
     * EXCHANGE_NAME: 这是交换机的名称，用来标识交换机。
     * true (durable): 交换机的持久性。如果设置为 true，则交换机会在 RabbitMQ 重启后继续存在（即，它会被持久化到磁盘上）。
     * false (autoDelete): 交换机的自动删除属性。如果设置为 false，即使没有队列与交换机绑定，交换机也不会自动删除。如果设置为 true，在与之绑定的队列删除后，交换机也会被删除。
     * @return  DirectExchange
     */





    @Bean
    public DirectExchange getDirectExchange(){
        return new DirectExchange(EXCHANGE_NAME,true,false);
    }

    @Bean
    public DirectExchange getDeadLetterDirectExchange(){
        return new DirectExchange(DEAD_LETTER_EXCHANGE_NAME,true,false);
    }

    /**
     * QUEUE_NAME: 队列名称，用来标识队列。
     * true (durable): 队列的持久性。如果设置为 true，则队列在 RabbitMQ 重启后依然存在（队列消息会被存储到磁盘上）。
     * false (exclusive): 独占性队列。如果设置为 true，该队列是专属队列，仅限于声明它的连接（Connection）使用。当连接关闭时，队列也会被删除。
     * false (autoDelete): 自动删除属性。如果设置为 false，即使队列没有使用，也不会自动删除。如果设置为 true，当没有消费者使用时队列会被自动删除。
     * null (arguments): 这是队列的额外参数，通常用于设置队列的 TTL（消息过期时间）等属性。null 表示没有附加参数。
     * @return
     */

    @Bean
    public Queue getQuene(){
        Map<String,Object> args = new HashMap<>();

        //设置消息的TTL 存活时间 模拟充电充满需要 半 分钟
        Integer ttl = 30 * 1000;
        args.put("x-message-ttl",ttl);

        //设置queue的死信Exchange
        args.put("x-dead-letter-exchange",DEAD_LETTER_EXCHANGE_NAME);
        //设置queue和死信Exchange 绑定 routing_key
        args.put("x-dead-letter-routing-key",DEAD_LETTER_ROUTING_KEY);

        //惰性队列,在消息很多的时候,把消息存储到磁盘,避免消息积压,占用内存
        args.put("x-queue-mode","lazy");

        return new Queue(QUEUE_NAME,true,false,false,args);
    }

    @Bean
    public Queue getDeadLetterQuene(){
        return new Queue(DEAD_LETTER_QUEUE_NAME,true,false,false,null);
    }


    /**
     * getQuene(): 这是绑定的队列，表示队列会通过 ROUTING_KEY 路由绑定到交换机上。
     * getDirectExchange(): 这是绑定的交换机，表示该队列通过 ROUTING_KEY 路由到这个 DirectExchange 交换机。
     * ROUTING_KEY: 路由键（Routing Key）用于确定消息如何路由到特定的队列。在 DirectExchange 中，消息会根据路由键精确匹配到绑定该路由键的队列上。
     * 总结
     * @return
     */

    @Bean
    public Binding getBind(){
        return BindingBuilder.bind(getQuene()).to(getDirectExchange()).with(ROUTING_KEY);
    }

    @Bean
    public Binding getDeadLetterBind(){
        return BindingBuilder.bind(getDeadLetterQuene()).to(getDeadLetterDirectExchange()).with(DEAD_LETTER_ROUTING_KEY);
    }

}
